#include <iostream>
#include <memory>
using namespace std;

class Point : public enable_shared_from_this<Point>{
public:
    Point(int x, int y)
    :_x(x)
    ,_y(y)
    {

    }

    //这里面依然是换汤不换药
    //利用当前的this指针创建了一个shared_ptr对象
    //但是该this指针又被另外一个sp所托管
    shared_ptr<Point> addPoint(Point * pt){
	_x += pt->_x;
	_y += pt->_y;
	//return shared_ptr<Point>(this);
    return shared_from_this();
    }

private:
    int _x;
    int _y;
};
//autorelease基本是一模一样的代码
void test0(){//error
//需要人为注意避免
Point * pt = new Point(1,2);
unique_ptr<Point> up(pt);
unique_ptr<Point> up2(pt);
}

//reset也是不可以的
void test1(){ //error
unique_ptr<Point> up(new Point(1,2));
unique_ptr<Point> up2(new Point(1,2));
//让两个unique_ptr对象托管了同一片空间
up.reset(up2.get());
}

//shared_ptr虽然可以共享所有权的智能指针，但是不是这种共享方法
//必须借助于拷贝构造函数、赋值运算符、移动构造、移动赋值运算函数才可以
void test2(){ // error
Point * pt = new Point(10,20);
shared_ptr<Point> sp(pt);
shared_ptr<Point> sp2(pt);
cout << sp.use_count() << endl;
cout << sp2.use_count() << endl;
}

void test3(){ //error
//使用不同的智能指针托管同一片堆空间
shared_ptr<Point> sp(new Point(1,2));
shared_ptr<Point> sp2(new Point(1,2));
sp.reset(sp2.get());
}

//shared_ptr如果希望能够共享引用计数，那么必须得通过正规的方式
//拷贝构造函数、赋值运算符函数、移动构造、移动赋值运算符函数
void test4(){
    //当创建sp的时候，内部的enable_shared_from_this类里面的数据成员
    //weak_ptr会初始化，并且指向了该对象
    //此时sp-------->Point对象
    //weak_ptr------->Point对象也是指向了该对象
    //并且二者是共享的
    //调用shared_from_this时，weak_ptr会升级为shared_ptr返回
    //只要能够和之前的sp共享，那么就没有问题
    shared_ptr<Point> sp(new Point(1, 2));
    shared_ptr<Point> sp2(new Point(3, 4));
    //sp->addPoint(sp2.get())返回的是指针实际上和sp托管的指针是一个
    //这同一个指针又被sp3所托管
    shared_ptr<Point> sp3(sp->addPoint(sp2.get()));
}

int main()
{
    test4();
    return 0;
}

